package com.zkyt.lib_msdk_ext.component.camera

import android.util.Log
import com.geoai.mavlink.geoainet.payload.enums.CameraImageStatus
import com.geoai.mavlink.geoainet.payload.enums.CameraLensType
import com.geoai.mavlink.geoainet.payload.enums.CameraMode
import com.geoai.mavlink.geoainet.payload.enums.CameraVideoStatus
import com.geoai.mavlink.geoainet.payload.enums.StorageFormatType
import com.geoai.mavlink.geoainet.payload.info.CameraCaptureStatusInfo
import com.geoai.mavlink.geoainet.payload.info.CameraHardwareInfo
import com.geoai.mavlink.geoainet.payload.info.CameraNewGeneratedInfo
import com.geoai.mavlink.geoainet.payload.info.CameraStorageInfo
import com.geoai.mavlink.geoainet.payload.interfaces.IBaseCameraListener
import com.zkyt.lib_msdk_ext.common.CompletionCbRxHandler
import com.zkyt.lib_msdk_ext.common.SDKExtUtil
import com.zkyt.lib_msdk_ext.component.IRemovableComp
import com.zkyt.lib_msdk_ext.component.ISDKExt
import com.zkyt.lib_msdk_ext.log.SDKExtLog
import io.reactivex.Completable
import io.reactivex.Observable
import io.reactivex.Single
import io.reactivex.subjects.BehaviorSubject
import java.util.Optional

/**
 * Created by chenyu on 2024/1/19
 * Description:
 */
object BaseCameraExt: ISDKExt<IBaseCameraListener>, IRemovableComp {
    private val isConnectSubject = BehaviorSubject.createDefault(false)
    private var baseCamera: IBaseCameraListener? = null
    private val advancedCameraExtProvider = AdvancedCameraExtProvider()

    private var orgCameraInfoObservable =
        BehaviorSubject.createDefault(Optional.empty<Pair<CameraLensType, CameraHardwareInfo>>())
    private var originNewGeneratedInfoObservable =
        BehaviorSubject.createDefault(Optional.empty<CameraNewGeneratedInfo>())
    private var orgCaptureInfoObservable =
        BehaviorSubject.createDefault(Optional.empty<Pair<CameraLensType, CameraCaptureStatusInfo>>())
    private var originCameraStorageInfoObservable =
        BehaviorSubject.createDefault(Optional.empty<CameraStorageInfo>())

    override fun init(originManager: IBaseCameraListener) {
        baseCamera = originManager

        baseCamera?.setCameraInformationListener { lens, info ->
            orgCameraInfoObservable.onNext(Optional.of(Pair(lens, info)))
        }
        baseCamera?.setNewGeneratedInfoListener {
            originNewGeneratedInfoObservable.onNext(Optional.of(it))
        }
        baseCamera?.setCaptureStatusListener { len, info ->
            orgCaptureInfoObservable.onNext(Optional.of(Pair(len, info)))
        }
        baseCamera?.setCameraStorageInfoListener {
            originCameraStorageInfoObservable.onNext(Optional.of(it))
        }
        SDKExtLog.i("BaseCameraExt", "init, got cameraType: ${baseCamera?.cameraModuleName}")
        advancedCameraExtProvider.init(baseCamera?.cameraModuleName!!, baseCamera!!)
        isConnectSubject.onNext(true)
    }
    override fun isConnected(): Boolean {
        return isConnectSubject.value!!
    }

    override fun getConnectedObservable(): Observable<Boolean> {
        return isConnectSubject.hide()
    }

    override fun destroy() {
        isConnectSubject.onNext(false)
        advancedCameraExtProvider.destroy()
        baseCamera?.setCameraInformationListener(null)
        baseCamera?.setNewGeneratedInfoListener(null)
        baseCamera?.setCaptureStatusListener(null)
        baseCamera?.setCameraStorageInfoListener(null)
        orgCameraInfoObservable.onNext(Optional.empty())
        originNewGeneratedInfoObservable.onNext(Optional.empty())
        orgCaptureInfoObservable.onNext(Optional.empty())
        originCameraStorageInfoObservable.onNext(Optional.empty())
        baseCamera = null
    }

    override fun getOriginManager(): IBaseCameraListener? {
        return baseCamera
    }

    fun getNV3Camera(): NV3CameraExt? {
        return advancedCameraExtProvider.getAdvancedCameraExt() as? NV3CameraExt
    }

    fun getAdvancedCameraExt(): IAdvancedCameraExt? {
        return advancedCameraExtProvider.getAdvancedCameraExt()
    }

    fun getNewGeneratedInfoObservable(): Observable<Optional<CameraNewGeneratedInfo>> {
        return originNewGeneratedInfoObservable.hide()
    }

    fun getCameraInfoObservable(): Observable<Optional<Pair<CameraLensType, CameraHardwareInfo>>> {
        return orgCameraInfoObservable.hide()
    }
    
    fun getCaptureInfoObservable(): Observable<Optional<Pair<CameraLensType, CameraCaptureStatusInfo>>> {
        return orgCaptureInfoObservable.hide()
    }

    fun getCameraStorageInfoObservable(): Observable<Optional<CameraStorageInfo>> {
        return originCameraStorageInfoObservable.hide()
    }

    fun startSingleCaptureRx(): Completable {
        return Completable.create { emitter ->
            baseCamera?.startSingleCapture(CompletionCbRxHandler(emitter))
        }
    }

    fun startRecordRx(): Completable {
        return Completable.create { emitter ->
            baseCamera?.startRecord(CompletionCbRxHandler(emitter))
        }
    }

    fun stopRecordRx(): Completable {
        return Completable.create { emitter ->
            baseCamera?.stopRecord(CompletionCbRxHandler(emitter))
        }
    }

    fun startComboCaptureRx(count: Int): Completable {
        return Completable.create { emitter ->
            baseCamera?.startComboCapture(count) {
                SDKExtUtil.handleError(emitter, it)
            }
        }
    }

    fun startIntervalCaptureRx(interval: Int): Completable {
        return Completable.create { emitter ->
            baseCamera?.startIntervalCapture(interval) {
                SDKExtUtil.handleError(emitter, it)
            }
        }
    }

    fun stopIntervalCaptureRx(): Completable {
        return Completable.create { emitter ->
            baseCamera?.stopIntervalCapture {
                SDKExtUtil.handleError(emitter, it)
            }
        }
    }

    fun getCameraModeRx() : Single<CameraMode> {
        return Single.create {
            it.onSuccess(orgCaptureInfoObservable.value?.get()?.second?.cameraMode?: CameraMode.UNKNOWN)
        }
    }
    
    fun setCameraModeRx(cameraMode: CameraMode): Completable {
        return Completable.create { emitter ->
            baseCamera?.setCameraMode(cameraMode,CompletionCbRxHandler(emitter))
        }
    }

    fun formatStorageRx(storageType: StorageFormatType): Completable {
        return Completable.create { emitter ->
            baseCamera?.formatStorage(storageType, CompletionCbRxHandler(emitter))
        }
    }
}